<template>
  <div class="image-list" style="width: 100%">
    <div v-for="(item, index) in imageList" :key="index" class="image-wrap">
      <el-image
        style="width: 100px; height: 100px"
        :src="item.url"
        fit="fill"
      ></el-image>
      <div class="icon-wrap">
        <el-icon @click.stop="handleRemove(item)">
          <Delete style="cursor: pointer" />
        </el-icon>
        &nbsp;&nbsp;
        <el-icon @click.stop="handlePictureCardPreview(item.url)">
          <View style="cursor: pointer" />
        </el-icon>
      </div>
    </div>
    <el-upload
      action="#"
      ref="uploadRef"
      class="image-uploader"
      :http-request="handleUpload"
      :show-file-list="false"
      :on-exceed="handleOnExceed"
      :multiple="multiple"
      :limit="limit"
    >
      <div style="display: flex">
        <el-icon class="actionIcon" style="margin-right: 10px">
          <Loading v-if="loading" />
          <Plus v-else />
        </el-icon>
        <el-icon class="actionIcon" @click.stop="openImagesPick">
          <Picture />
        </el-icon>
      </div>
    </el-upload>
    <!-- 图片预览 -->
    <el-image-viewer
      v-if="viewVisible"
      :zoom-rate="1.2"
      :initial-index="initialIndex"
      :url-list="viewFileList"
      @close="closePreview"
    />
    <ra-file-picker
      ref="refFilePicker"
      :multiple="multiple"
      :onlyImage="true"
      @update="updateSelect"
    />
  </div>
</template>
<script setup>
/**
 * 单图片、多图片
 * 缩略图
 */
import { smartTranslate as $t } from '@/lang';
import AdminFileAPI from '@/api/admin/admin/file';
import { clone } from 'xe-utils';

const props = defineProps({
  modelValue: {
    type: [Array, String],
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  limit: {
    type: Number,
    default: 1,
  },
});
const emit = defineEmits(['update:modelValue', 'change']);
const uploadRef = ref();
const imageList = ref(props.modelValue);
const loading = ref(false);
const viewVisible = ref(false);
const viewFileList = ref([]);
const initialIndex = ref(0);

watch(
  () => props.modelValue,
  (newVal) => {
    if (typeof newVal === 'string') {
      imageList.value = newVal ? [{ url: newVal }] : [];
    } else if (Array.isArray(newVal)) {
      if (newVal.length > props.limit) {
        ElMessage.error(
          $t('common.message.upload.max', {
            max: props.limit,
          }),
        );
        return;
      }
      // 如果 newVal 是数组，则遍历数组并创建带有 url 属性的对象数组
      imageList.value = newVal
        .map((item) => {
          if (typeof item === 'string') {
            return { url: item };
          } else if (
            typeof item === 'object' &&
            item !== null &&
            'url' in item
          ) {
            // 如果已经是带有 url 属性的对象，则直接返回
            return { ...item }; // 也可以选择只保留 url 属性，取决于你的需求
          } else {
            console.warn('Invalid item in array:', item);
            return null; // 或者你可以选择跳过无效项
          }
        })
        .filter((item) => item !== null); // 过滤掉无效项
    } else {
      imageList.value = [];
    }
  },
  { immediate: true },
);

// 执行上传
const handleUpload = (options) => {
  loading.value = true;
  AdminFileAPI.add(options.file)
    .then(({ data }) => {
      ElMessage.success(
        $t('common.message.success.general', {
          action: $t('common.action.upload'),
        }),
      );
      if (props.multiple) {
        imageList.value.push(data);
      } else {
        imageList.value = [data];
      }
      updataModelValue(imageList.value);
    })
    .catch(() => {
      ElMessage.error(
        $t('common.message.failed.general', {
          action: $t('common.action.upload'),
        }),
      );
    })
    .finally(() => {
      loading.value = false;
    });
};

// 超过了上传限制
const handleOnExceed = (files) => {
  imageList.value = [];
  handleUpload({ file: files[0] });
};

// 图片选择
const refFilePicker = ref();
const openImagesPick = () => {
  refFilePicker.value.show();
};
const updateSelect = (data) => {
  updataModelValue(data);
};

// 删除图片
const handleRemove = (file) => {
  imageList.value = imageList.value.filter((item) => item.url !== file.url);
  updataModelValue(imageList.value);
};

// 预览图片
const handlePictureCardPreview = (fileUrl) => {
  viewFileList.value = imageList.value.map((item) => item.url);
  initialIndex.value = viewFileList.value.findIndex((url) => url === fileUrl);
  viewVisible.value = true;
};

// 关闭预览界面
const closePreview = () => {
  viewVisible.value = false;
};

// 更新V-modelValue
const updataModelValue = (imageList) => {
  const fileList = clone(imageList);
  const urlList = fileList.map((file) => file.url);
  const newValue = props.multiple ? urlList : urlList[0];
  emit('update:modelValue', newValue);
  emit('change', newValue);
};
</script>

<style lang="scss" scoped>
.image-list {
  display: flex;
  flex-wrap: wrap;

  .image-wrap {
    position: relative;
    width: 100px;
    height: 100px;
    border: 1px solid #d9d9d9;
    border-radius: 6px;
    overflow: hidden;
    margin-right: 10px;

    .imgStyle {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;

      img {
        max-width: 100%;
        max-height: 100%;
      }
    }

    .icon-wrap {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      height: 30%;
      background-color: rgba(0, 0, 0, 0.5);
      color: white;
      display: flex;
      align-items: center;
      justify-content: space-around;
      padding: 10px;
      font-size: 1.2em;
    }
  }

  .image-uploader {
    display: inline-block;
    width: 100px;
    height: 100px;
    line-height: 110px;
    text-align: center;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    i {
      font-size: 28px;
      color: #8c939d;
    }

    &:hover {
      border-color: #409eff;
    }
  }
  .actionIcon {
    &:hover {
      color: #67c23a;
    }
  }
}
</style>
